package com.adam.example;

import co.elastic.clients.elasticsearch.ElasticsearchClient;
import co.elastic.clients.elasticsearch._types.ErrorCause;
import co.elastic.clients.elasticsearch._types.ScriptLanguage;
import co.elastic.clients.elasticsearch._types.mapping.DateProperty;
import co.elastic.clients.elasticsearch._types.mapping.Property;
import co.elastic.clients.elasticsearch._types.mapping.TextProperty;
import co.elastic.clients.elasticsearch.core.*;
import co.elastic.clients.elasticsearch.core.bulk.BulkResponseItem;
import co.elastic.clients.elasticsearch.core.mget.MultiGetResponseItem;
import co.elastic.clients.elasticsearch.indices.CreateIndexResponse;
import co.elastic.clients.elasticsearch.indices.DeleteIndexResponse;
import co.elastic.clients.json.JsonData;
import co.elastic.clients.json.JsonpMapper;
import com.adam.example.types.Book;
import com.adam.example.types.Tweet;
import jakarta.json.spi.JsonProvider;

import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.text.ParseException;
import java.util.List;

public class DocumentManagementExample {

    public static void main(String[] args) throws IOException, ParseException {
        ElasticsearchClient client = ElasticsearchClientHolder.getINSTANCE().initializeAndGetClient();

        Book book = new Book(7L, "Spring技术内幕", "Spring参考书", "计文柯", "java", 60.2, "2016-04-01");
        IndexResponse indexResponse = client.index(builder -> builder
                .index("test_books").id("7").document(book)
        );
        System.out.println("创建文档：" + indexResponse.result());

        GetResponse<Book> getResponse = client.get(builder -> builder
                .index("test_books").id("7"), Book.class
        );
        System.out.println("获取文档：" + getResponse.source());

        Book book1 = new Book(null, null, null, null, null, null, "2016-04-02");
        UpdateResponse<Book> updateResponse = client.update(builder -> builder
                .index("test_books").id("7").doc(book1), Book.class);
        System.out.println("更新文档：" + updateResponse.result());

        UpdateResponse<Book> updateResponse1 = client.update(builder -> builder
                .index("test_books").id("7").script(scriptBuilder -> scriptBuilder
                        .inline(inlineScriptBuilder -> inlineScriptBuilder
                                .lang(ScriptLanguage.Painless).source("ctx._source.price = 60.3")
                        )
                ), Book.class
        );
        System.out.println("更新文档：" + updateResponse1.result());

        GetResponse<Book> getResponse1 = client.get(builder -> builder
                .index("test_books").id("7"), Book.class
        );
        System.out.println("更新后获取文档：" + getResponse1.source());

        DeleteResponse deleteResponse = client.delete(builder -> builder
                .index("test_books").id("7")
        );
        System.out.println("删除文档：" + deleteResponse.result());

        MgetResponse<Book> mgetResponse = client.mget(builder -> builder
                .index("test_books").ids("1", "3", "5"), Book.class
        );
        List<MultiGetResponseItem<Book>> multiGetResponseItemList = mgetResponse.docs();
        for(int i=0;i< multiGetResponseItemList.size();i++) {
            MultiGetResponseItem<Book> multiGetResponseItem = multiGetResponseItemList.get(i);
            Book book2 = multiGetResponseItem.result().source();
            System.out.println("获取文档[" + (i+1) + "]:" + book2);
        }

        CreateIndexResponse createIndexResponse = client.indices().create(builder ->
                builder.index("test_twitter").settings(indexSettingsBuilder -> indexSettingsBuilder
                        .numberOfReplicas("0").numberOfShards("1")
                ).mappings(typeMappingBuilder -> typeMappingBuilder
                        .properties("message", Property.of(propertyBuilder -> propertyBuilder
                                .text(TextProperty.of(textPropertyBuilder -> textPropertyBuilder))
                        ))
                        .properties("timestamp", Property.of(propertyBuilder -> propertyBuilder
                                .date(DateProperty.of(datePropertyBuilder -> datePropertyBuilder))
                        ))
                )
        );
        System.out.println("创建索引test_twitter:" + createIndexResponse.acknowledged());

        String rawTweetJson = "{\"message\": \"tweet3\", \"timestamp\": \"2025-06-08\"}";
        ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(rawTweetJson.getBytes(StandardCharsets.UTF_8));
        JsonpMapper jsonpMapper = client._jsonpMapper();
        JsonProvider jsonProvider = jsonpMapper.jsonProvider();
        JsonData jsonData = JsonData.from(jsonProvider.createParser(byteArrayInputStream), jsonpMapper);
        BulkRequest bulkRequest = new BulkRequest.Builder()
                .operations(builder -> builder
                        .index(indexOperationBuilder -> indexOperationBuilder
                                .index("test_twitter")
                                .id("1")
                                .document(new Tweet("tweet1", "2025-06-09"))
                        )
                )
                .operations(builder -> builder
                        .index(indexOperationBuilder -> indexOperationBuilder
                                .index("test_twitter")
                                .id("2")
                                .document(new Tweet("tweet2", "2025-06-09"))
                        )
                )
                .operations(builder -> builder
                        .update(updateOperationBuilder -> updateOperationBuilder
                                .index("test_twitter")
                                .id("2")
                                .action(updateActionBuilder -> updateActionBuilder
                                        .doc(new Tweet("tweet2 updated", null))
                                )
                        )
                )
                .operations(builder -> builder
                        .delete(deleteOperationBuilder -> deleteOperationBuilder
                                .index("test_twitter")
                                .id("1")
                        )
                )
                .operations(builder -> builder
                                .index(indexOperationBuilder -> indexOperationBuilder
                                        .index("test_twitter")
                                        .id("3")
                                        .document(jsonData)
                        )
                )
                .build();
        BulkResponse bulkResponse = client.bulk(bulkRequest);
        //也可以使用异步客户端asyncClient.bulk(bulkRequest).whenComplete((bulkResponse, throwable) -> {...})方法添加回调函数处理异常和返回结果
        List<BulkResponseItem> bulkResponseItemList = bulkResponse.items();
        for (int i = 0; i < bulkResponseItemList.size(); i++) {
            BulkResponseItem bulkResponseItem = bulkResponseItemList.get(i);
            System.out.println("Bulk请求[" + (i + 1) + "]:" + bulkResponseItem.result());
            if (bulkResponseItem.error() != null) {
                ErrorCause errorCause = bulkResponseItem.error();
                System.err.println("发生异常！异常类型：" + errorCause.type() + ",异常原因：" + errorCause.reason());
            }
        }
//        byteArrayInputStream.close();   //No-op

        MgetResponse<Tweet> mgetResponse1 = client.mget(builder -> builder
                .index("test_twitter").ids("1","2", "3"), Tweet.class);
        List<MultiGetResponseItem<Tweet>> multiGetResponseItemList1 = mgetResponse1.docs();
        for(int i=0;i< multiGetResponseItemList1.size();i++) {
            MultiGetResponseItem<Tweet> multiGetResponseItem = multiGetResponseItemList1.get(i);
            Tweet tweet = multiGetResponseItem.result().source();
            System.out.println("Bulk请求后获取文档[" + (i+1) + "]:" + tweet);
        }

        DeleteIndexResponse deleteIndexResponse = client.indices().delete(builder ->
                builder.index("test_twitter")
        );
        System.out.println("删除索引test_twitter:" + deleteIndexResponse.acknowledged());

        ElasticsearchClientHolder.getINSTANCE().close();
    }

}
